/*
  This file is part of JCM.

  JCM is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  JCM is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with JCM.  If not, see <http://www.gnu.org/licenses/>.
*/
/**
 * Classe para computação da média aritimética e respectivo desvio padrão
 * menos propensa a erros de representação numérica.
 *
 * @param <N> Tipo numérico.
*/
public class Stat<N extends Number>
{
  /** O número de observações da variável aleatória. */
  private int n;

  /** O valor da média aritimética. */
  private double mean;

  /** A soma dos quadrado dos residuos. */
  private double sum;   // sum of square

  /** Construtor do objeto inicializando as propriedades. */
  public Stat()
  {
    n = 0;
    mean = Double.NaN;
    sum = Double.NaN;
  }

  /**
   * Retorna o número de observações da variável aleatória.
   *
   * @return O número de observações da variável aleatória.
  */
  public int getSize() { return n; }

  /**
   * Retorna a média aritimética da variável aleatória.
   *
   * @return A média aritimética da variável aleatória.
  */
  public double getMean() { return mean; }

  /**
   * Retorna a soma dos valôres observados.
   *
   * @return A soma dos valôres observados.
  */
  public double getTotal() { return mean * n; }

  /**
   * Retorna a soma dos quadrados dos residuos.
   *
   * @return A soma dos quadrados dos residuos.
  */
  public double getSum() { return sum; }

  /**
   * Retorna o desvio padrão amostral da média aritimética das observações.
   *
   * @return O desvio padrão amostral da média aritimética das observações
   *         para número de observações maior que 1 caso contrário retorna
   *         zero.
  */
  public double getStdDeviation()
  {
    return n < 2 ? 0 : Math.sqrt(sum / (n - 1));
  }

  /**
   * Inclue uma observação da variável aleatória na estatítica usando o
   * método UPDATE menos propenso a erros de representação numérica.
   *
   * @param x Valor numérico da observação.
  */
  public void add(N x)
  {
    if (n > 0) {
      double aux = x.doubleValue() - mean;
      n++;
      mean += aux / n;
      sum += (n - 1) * aux * aux / n;
    } else {
      n = 1;
      mean = x.doubleValue();
      sum = 0;
    }
  }

  /*public void remove(N x)
  {
    if (n > 1) mean = (mean * n - x.doubleValue()) / --n;
    else {
      mean = Double.NaN;
      n = 0;
    }
  }

  public void replace(N x, N y)
  {
    if ((n > 0) && (Math.abs(x.doubleValue() - y.doubleValue()) > EPS)) {
      if (n == 1) mean = y.doubleValue();
      else {
        mean += (y.doubleValue() - x.doubleValue()) / n;
      }
    }
  }

  public static final double EPS = 1E-9; */
}